package com.ebs.md.api.abs;

/**
 * Perforce Revision:
 *  $File: //depot/MarketData/commons-md-api/MAIN/src/main/java/com/ebs/md/api/abs/AbsMultilpleBooksManager.java $
 *  $Revision: #6 $  $Change: 115607 $  $DateTime: 2012/10/11 15:02:25 $  $Author: Arik.Sher $
 */

import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import org.apache.log4j.Logger;

import com.ebs.md.api.BookSide;
import com.ebs.md.api.IBookEntry;
import com.ebs.md.api.IOrder;
import com.ebs.md.api.IOrderBook;
import com.ebs.md.api.IOrderBookManager;
import com.ebs.md.api.IProduct;
import com.ebs.md.api.ISnapshot;
import com.ebs.md.api.OrderBookListener;
import com.ebs.md.api.Rate;

/**
 * Manages multiple OrderBooks, one per IProduct(CurrencyPair)
 *
 * @param <BE>
 * @param <O>
 */
public abstract class AbsMultilpleBooksManager<BE extends IBookEntry, O extends IOrder>
implements IOrderBookManager<BE, O>
{
    protected  final Logger         logger = Logger.getLogger(getClass());

    protected ConcurrentMap<IProduct, IOrderBookManager<BE, O> > booksMap = new ConcurrentHashMap<IProduct, IOrderBookManager<BE, O> >(16);
	
    protected OrderBookListener<IOrderBook<BE>, BE, O> orderBookListener;

	public void applyOrder(O order) {
		if ( order == null ) {
			return;
		}
		IOrderBookManager<BE, O> orderBookManager = booksMap.get(order.getProduct());
		
		if ( orderBookManager != null ) {
			orderBookManager.applyOrder(order);
		} else {
			//TODO: log that Book for this product is not initialized 
		}
	}

	public void resetSnapshotSide(ISnapshot<BE> snapshot) {
		IProduct product = snapshot.getProduct();
		if ( !isProductSupported(product) ) {
			logger.info(String.format("product '%s' is not supported", product.getName()));
			return;
		}
		
		IOrderBookManager<BE, O> orderBookManager = booksMap.get(product);
		
		if ( orderBookManager == null ) {
			orderBookManager = createOrderBookManager(product);
			booksMap.put(product, orderBookManager);
			orderBookManager.setOrderBookListener(orderBookListener);
		}
		
		orderBookManager.resetSnapshotSide(snapshot);
	}
	
	public void resetWithSnapshot(ISnapshot<BE> bidSideSnapshot, ISnapshot<BE> offerSideSnapshot) {
		IProduct product = bidSideSnapshot.getProduct();
		if ( !isProductSupported(product) ) {
			logger.info(String.format("product '%s' is not supported", product.getName()));
			return;
		}

		IOrderBookManager<BE, O> orderBookManager = booksMap.get(product);
		
		if ( orderBookManager == null ) {
			orderBookManager = createOrderBookManager(product);
			booksMap.put(product, orderBookManager);
			orderBookManager.setOrderBookListener(orderBookListener);
		}
		
		orderBookManager.resetWithSnapshot(bidSideSnapshot, offerSideSnapshot);
	}
	
	public void setOrderBookListener(OrderBookListener<IOrderBook<BE>, BE, O> listener) {
		orderBookListener = listener;
	}

	/**
	 * determines wether product is supported and should be managed.
	 * if true than createOrderBookManager should return value. 
	 * 
	 * @param product
	 * @return
	 */
	abstract protected boolean isProductSupported(IProduct product);

	/**
	 * 
	 * @param product
	 * @return 
	 */
	abstract protected IOrderBookManager<BE, O> createOrderBookManager(IProduct product);


	public List<BE> getAllBids() {
		throw new UnsupportedOperationException("the MultipleBooks manager does support this method");
	}
	public List<BE> getAllOffers() {
		throw new UnsupportedOperationException("the MultipleBooks manager does support this method");
	}
	public IProduct getProduct() {
		throw new UnsupportedOperationException("the MultipleBooks manager does support this method");
	}
	public List<Rate> getTopBidRates(int maxItems) {
		throw new UnsupportedOperationException("the MultipleBooks manager does support this method");
	}
	public List<BE> getTopBidsAtRate(Rate rate, int maxItems) {
		throw new UnsupportedOperationException("the MultipleBooks manager does support this method");
	}
	public List<Rate> getTopOfferRates(int maxItems) {
		throw new UnsupportedOperationException("the MultipleBooks manager does support this method");
	}
	public List<BE> getTopOffersAtRate(Rate rate, int maxItems) {
		throw new UnsupportedOperationException("the MultipleBooks manager does support this method");
	}
	public Rate getBestBid() {
		throw new UnsupportedOperationException("the MultipleBooks manager does support this method");
	}
	public Rate getBestOffer() {
		throw new UnsupportedOperationException("the MultipleBooks manager does support this method");
	}
	public int getBidEntriesCountAtRate(Rate rate) {
		throw new UnsupportedOperationException("the MultipleBooks manager does support this method");
	}
	public int getBidRatesCount() {
		throw new UnsupportedOperationException("the MultipleBooks manager does support this method");
	}
	public int getOfferEntriesCountAtRate(Rate rate) {
		throw new UnsupportedOperationException("the MultipleBooks manager does support this method");
	}
	public int getOfferRatesCount() {
		throw new UnsupportedOperationException("the MultipleBooks manager does support this method");
	}
	public Rate getWorstBid() {
		throw new UnsupportedOperationException("the MultipleBooks manager does support this method");
	}
	public Rate getWorstOffer() {
		throw new UnsupportedOperationException("the MultipleBooks manager does support this method");
	}
	public Rate getNextBestRate(BookSide side, Rate rate) {
		throw new UnsupportedOperationException("the MultipleBooks manager does support this method");
	}
	public Rate getNextBestBid(Rate rate) {
		throw new UnsupportedOperationException("the MultipleBooks manager does support this method");
	}
	public Rate getNextBestOffer(Rate rate) {
		throw new UnsupportedOperationException("the MultipleBooks manager does support this method");
	}

}
